/**
 * @file literal-buffer.cc
 * @author your name (you@domain.com)
 * @brief 
 * @version 0.1
 * @date 2024-04-01
 * 
 * @copyright Copyright (c) 2024
 * 
 */
#include "src/parsing/literal-buffer.h"

int LiteralBuffer::NewCapacity(int min_capacity) {
    return min_capacity < (kMaxGrowth / (kGrowthFactor - 1))
        ? min_capacity * kGrowthFactor
        : min_capacity + kMaxGrowth;
}

void LiteralBuffer::ConvertToTwoByte() {
    base::Vector<byte> new_store;
    int new_content_size = position_ * base::kUC16Size;
    if (new_content_size >= backing_store_.length()) {
        new_store = base::Vector<byte>::New(NewCapacity(new_content_size));
    } else {
        new_store = backing_store_;
    }

    uint8_t* src = backing_store_.begin();
    uint16_t* dst = reinterpret_cast<uint16_t*>(new_store.begin());
    for (int i = position_ - 1; i >= 0; i--) {
        dst[i] = src[i];
    }

    if (new_store.begin() != backing_store_.begin()) {
        backing_store_.Dispose();
        backing_store_ = new_store;
    }

    position_ = new_content_size;
    is_one_byte_ = false;
}

void LiteralBuffer::AddTwoByteChar(base::uc32 code_unit) {
    if (position_ >= backing_store_.length()) ExpandBuffer();
    if (code_unit <= static_cast<base::uc32>(unibrow::Utf16::kMaxNonSurrogateCharCode)) {
        *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = code_unit;
        position_ += base::kUC16Size;
    } else {
        *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = unibrow::Utf16::LeadSurrogate(code_unit);
        position_ += base::kUC16Size;
        if (position_ >= backing_store_.length()) ExpandBuffer();
        *reinterpret_cast<uint16_t*>(&backing_store_[position_]) = unibrow::Utf16::TrailSurrogate(code_unit);
        position_ += base::kUC16Size; 
    }
}